﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace Common
{
    /// <summary>
    /// 安全加密管理器
    /// </summary>
    /// <remarks>
    /// 保持与原  一致，以保证适应原来加解密。
    /// </remarks>
    public static class CipherManager
    {
        private const string HEAD_SALT = "{6DD9A6D9-E119-4407-A469-53A9A1FF5ACE}";
        private const string TAIL_SALT = "{F49536D3-B070-49a5-A0ED-858683547CDF}";
        private const string HeadSalt_Password = "{998DAA57-E0B5-479b-B82D-6D152A89B205}";
        private const string TailSalt_Password = "{0AA918AC-478B-46fe-9C07-B4319014AA3A}";
        private static readonly string MEMBER_CIPHER = ")(*&^%$#@!QAZSEDCRTYTGBUJMIK<L?:P{P:?>";

        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="rawKey"></param>
        /// <returns></returns>
        public static string DecryptCipher(byte[] rawKey)
        {
            byte[] key = GetCryptographyKey();
            byte[] iv = GetIVByKey(key);

            Aes aes = Aes.Create();
            MemoryStream cache = new MemoryStream();
            CryptoStream stream = new CryptoStream(cache, aes.CreateDecryptor(key, iv), CryptoStreamMode.Write);

            stream.Write(rawKey, 0, rawKey.Length);
            stream.FlushFinalBlock();

            byte[] data = cache.ToArray();

            return Encoding.Unicode.GetString(data);
        }

        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="cipher"></param>
        /// <returns></returns>
        public static byte[] EncryptCipher(string cipher)
        {
            byte[] data = Encoding.Unicode.GetBytes(cipher);
            byte[] key = GetCryptographyKey();
            byte[] iv = GetIVByKey(key);

            Aes aes = Aes.Create();
            MemoryStream cache = new MemoryStream();
            CryptoStream stream = new CryptoStream(cache, aes.CreateEncryptor(key, iv), CryptoStreamMode.Write);

            stream.Write(data, 0, data.Length);
            stream.FlushFinalBlock();

            return cache.ToArray();
        }

        private static byte[] GetCryptographyKey()
        {
            string rawKey = HEAD_SALT + MEMBER_CIPHER + TAIL_SALT;

            SHA256 sha = SHA256.Create();

            return sha.ComputeHash(Encoding.UTF8.GetBytes(rawKey));
        }

        private static byte[] GetIVByKey(byte[] key)
        {
            byte[] iv = new byte[key.Length / 2];

            Array.Copy(key, iv, iv.Length);

            return iv;
        }

        /// <summary>
        /// 对传入的密码进行安全处理
        /// </summary>
        /// <param name="password">待处理的密码</param>
        /// <returns></returns>
        public static string EncryptPassword(string password)
        {
            string token = HeadSalt_Password + password + TailSalt_Password;
            byte[] inputData = Encoding.Default.GetBytes(token);

            SHA1 sha = SHA1.Create();
            byte[] result = sha.ComputeHash(inputData);

            var sb = new StringBuilder();

            foreach (byte data in result)
            {
                sb.Append(data.ToString("X2"));
            }

            return sb.ToString();
        }
    }
}
